package com.zhengqing.system.util;

import com.zhengqing.common.core.util.ApplicationContextHelper;
import com.zhengqing.system.config.MinIoTsProperties;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * MinIo工具类
 *
 * @author wqy
 * @date 2021/03/12
 */
@Slf4j
public class MinIoUtil {

    /**
     * 上传file文件
     *
     * @param file       file
     * @param bucketName bucketName
     * @param objectName objectName
     * @throws Exception e
     */
    public static void uploadFile(MultipartFile file, String bucketName, String objectName) throws Exception {
        MinioClient minioClient = getMiniClient();
        createBucket(minioClient, bucketName);
        minioClient.putObject(PutObjectArgs.builder()
                .stream(file.getInputStream(), file.getSize(), PutObjectArgs.MAX_PART_SIZE)
                .object(objectName)
                .contentType(file.getContentType())
                .bucket(bucketName)
                .build());
        log.info(file.getOriginalFilename() + " is successfully uploaded as "
                + "object " + objectName + " to bucket " + bucketName + ".");
    }

    /**
     * 上传file文件
     *
     * @param bucketName bucketName
     * @param objectName objectName
     * @throws Exception e
     */
    public static void uploadFile(byte[] bytes, String bucketName, String objectName) throws Exception {
        MinioClient minioClient = getMiniClient();
        createBucket(minioClient, bucketName);
        minioClient.putObject(PutObjectArgs.builder()
                .stream(new ByteArrayInputStream(bytes), bytes.length, PutObjectArgs.MAX_PART_SIZE)
                .object(objectName)
                .bucket(bucketName)
                .contentType("application/pdf")
                .build());
        log.info(objectName + " is successfully uploaded as "
                + "object " + objectName + " to bucket " + bucketName + ".");
    }


    /**
     * 上传file文件
     *
     * @param bucketName bucketName
     * @param objectName objectName
     * @throws Exception e
     */
    public static void uploadFile(InputStream inputStream, String bucketName, String objectName,long objectSize) throws Exception {
        MinioClient minioClient = getMiniClient();
        createBucket(minioClient, bucketName);
        minioClient.putObject(PutObjectArgs.builder()
                .stream(inputStream, objectSize, PutObjectArgs.MAX_PART_SIZE)
                .object(objectName)
                .bucket(bucketName)
                .build());
        log.info("file  is successfully uploaded as "
                + "object " + objectName + " to bucket " + bucketName + ".");
    }

    /**
     * 创建桶
     *
     * @param minioClient minioClient
     * @param bucketName  bucketName
     * @throws Exception e
     */
    public static void createBucket(MinioClient minioClient, String bucketName) throws Exception {
        boolean found =
                minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!found) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        } else {
            log.info("Bucket " + bucketName + " already exists.");
        }
    }

    /**
     * 获取MinIO链接
     *
     * @return MinIoClient
     */
    public static MinioClient getMiniClient() {
        MinIoTsProperties minIoProperties = ApplicationContextHelper.popBean(MinIoTsProperties.class);
        return MinioClient.builder()
                .endpoint(Objects.requireNonNull(minIoProperties, "minIoTsProperties不能为空").getUrl())
                .credentials(minIoProperties.getAccessKey(), minIoProperties.getSecretKey())
                .build();
    }

    public static MinioClient getEndMiniClient() {
        MinIoTsProperties minIoProperties = ApplicationContextHelper.popBean(MinIoTsProperties.class);
        return MinioClient.builder()
                .endpoint(Objects.requireNonNull(minIoProperties, "minIoTsProperties不能为空").getUrl())
                .credentials(minIoProperties.getAccessKey(), minIoProperties.getSecretKey())
                .endpoint(minIoProperties.getEndUrl())
                .build();
    }

    /**
     * 根据文件名生成ObjectName
     *
     * @param fileType   fileType
     * @param bucketName bucketName
     * @return String
     */
    public static String getObjectName(String fileType, String bucketName) {
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return bucketName + "_" + uuid + "." + fileType;
    }

    /**
     * 根据文件名称获得流
     *
     * @param bucketName 桶名称
     * @param objectName 文件名称
     * @return InputStream
     * @throws Exception e
     */
    public static InputStream getObject(String bucketName, String objectName) throws Exception {
        MinioClient minioClient = getMiniClient();
        InputStream stream = minioClient.getObject(GetObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build());
        if (Objects.isNull(stream)) {
            throw new RuntimeException("未找到改文件！");
        }
        return stream;
    }

    /**
     * 根据文件名称获得流
     *
     * @param bucketName 桶名称
     * @param objectName 文件名称
     * @return InputStream
     * @throws Exception e
     */
    public static String getObjectUrl(String bucketName, String objectName,Integer expires) throws Exception {
        MinioClient minioClient = getMiniClient();
        String presignedObjectUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .expiry(expires)
                        .bucket(bucketName)
                        .object(objectName)
                        .build());
        return StringUtils.isBlank(presignedObjectUrl)? Strings.EMPTY:presignedObjectUrl;
    }

}
